//
// RS Game Framework
// Copyright © 2009 Jedd Haberstro
// jhaberstro@gmail.com
// 
// $Id:
//

#include "rs/Condition.hpp"
#include "rs/Mutex.hpp"
#include "rs/portability/platforms/posix/Implementations.hpp"
#include <algorithm>
#include <pthread.h>

namespace rs
{
    Condition::Condition()
    : implementation_(new internal::ConditionImplementation) {
        int err = pthread_cond_init(&implementation_->conditionHandle_, 0);
        RS_ASSERTF(err == 0, "Creating pthread condition variable failed with error code: %i", err);
    }
    
    Condition::Condition(Condition const& other)
    : implementation_(other.implementation_) {
    }
    
    Condition::~Condition() {
        int err = pthread_cond_destroy(&implementation_->conditionHandle_);
        RS_ASSERTF(err == 0, "Destroying pthread condition variable failed with error code: %i", err);
    }
    
    void Condition::BroadcastSignal() {
        int err = pthread_cond_broadcast(&implementation_->conditionHandle_);
        RS_ASSERTF(err == 0, "Broadcasting pthread condition variable failed with error code: %i", err);
    }
    
    void Condition::Signal() {
        int err = pthread_cond_signal(&implementation_->conditionHandle_);
        RS_ASSERTF(err == 0, "Signaling pthread condition variable failed with error code: %i", err);        
    }    

    void Condition::Wait(Mutex& mutex) {
        int err = pthread_cond_wait(&implementation_->conditionHandle_, &mutex.implementation_->mutexHandle_);
        RS_ASSERTF(err == 0, "Waiting on pthread condition variable failed with error code: %i", err);        
    }
    
    void Condition::Swap(Condition& other) {
        std::swap(implementation_, other.implementation_);
    }
    
    Condition& Condition::operator=(Condition const& other) {
        if (this != &other) {
            Condition(other).Swap(*this);
        }
        
        return *this;
    }
}